package com.first.nell.info.face

import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.Matrix
import android.util.Size
import android.view.View
import android.widget.Toast
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview
import androidx.camera.core.resolutionselector.ResolutionSelector
import androidx.camera.core.resolutionselector.ResolutionStrategy
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.content.ContextCompat
import androidx.exifinterface.media.ExifInterface
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.first.nell.base.BaseActivity
import com.first.nell.data.ReqImageUpload
import com.first.nell.databinding.ActivityFirstNellFaceDoingBinding
import com.first.nell.enums.PageTagEnum
import com.first.nell.extend.*
import com.first.nell.info.idcard.IdentityCardModel
import com.first.nell.launch.UserStateViewModel
import com.first.nell.utils.imageUtil.ImageConvert
import java.io.File
import java.io.IOException
import java.util.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors


@SuppressLint("CustomSplashScreen")
class FaceDoingActivity : BaseActivity() {

    private lateinit var mFirstNellActivityFirstNellBinding: ActivityFirstNellFaceDoingBinding
    private lateinit var carmeraExecutor: ExecutorService

    private var imageCapture: ImageCapture? = null
    private var mImageLocalPath: String? = null
    private var mImageBitmap: Bitmap? = null

    private val mIdentityCardModel by lazy {
        ViewModelProvider(this)[IdentityCardModel::class.java]
    }

    private val mUserStateViewModel by lazy {
        ViewModelProvider(this)[UserStateViewModel::class.java]
    }

    override fun onFirstNellBindingFirstNellViewFirstNellModel(): List<ViewModel>? {
        val list = mutableListOf<ViewModel>()
        list.add(mUserStateViewModel)
        list.add(mIdentityCardModel)
        return list
    }

    override fun onFirstNellBindingFirstNellViewFirstNellTag(): String {
        return PageTagEnum.selfie.name.uppercase()
    }

    override fun onFirstNellBindingFirstNellContentFirstNellView(): View {
        mFirstNellActivityFirstNellBinding = ActivityFirstNellFaceDoingBinding.inflate(layoutInflater)
        return mFirstNellActivityFirstNellBinding.root
    }

    override fun onDestroy() {
        super.onDestroy()
        carmeraExecutor.shutdown()
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun onFirstNellContentFirstNellViewFirstNellBinded() {
        try {
            //初始化拍照与选择图片回调
            carmeraExecutor = Executors.newSingleThreadExecutor()

            //take picture
            mFirstNellActivityFirstNellBinding.llTakePicture.setOnClickListener {
                mFirstNellActivityFirstNellBinding.llTakePicture.recordFirstNellClickFirstNellEvent()
                takePhoto()
            }

            //retake
            mFirstNellActivityFirstNellBinding.llRetake.setOnClickListener {
                mFirstNellActivityFirstNellBinding.llRetake.recordFirstNellClickFirstNellEvent()
                //重置UI
                updateTakePictureUI(null)
            }

            //commit
            mFirstNellActivityFirstNellBinding.llChoose.setOnClickListener {
                mFirstNellActivityFirstNellBinding.llChoose.recordFirstNellClickFirstNellEvent()
                val path = mImageLocalPath
                FaceDetectManager.setFaceDetectState(true, path, mImageBitmap)
                finish()
            }

            //直接请求完权限后，启动相机预览
            requestExtPermissoins()

        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun isFirstNellAllFirstNellFormFirstNellDataFirstNellCompleted(): String {
        val notFillOptions = mutableListOf<String>()

        return notFillOptions.joinToString("#")
    }

    override fun onFirstNellPermissionsFirstNellRequestFirstNellAllFirstNellPass() {
        //启动相机预览
        startCameraPreview()
    }

    /** 处理选择/拍照回调 */
    private fun onHandlerImagePickResult(covetPath: String?, bitmap: Bitmap?) {
        if (covetPath?.isNotBlank() == true) {
            mIdentityCardModel.mFirstNellImageFirstNellPathFirstNellFront = covetPath
            mIdentityCardModel.mFirstNellImageFirstNellBitmapFirstNellFront = bitmap

            //上传图片
            mIdentityCardModel.uploadFirstNellImage(
                ReqImageUpload(
                    filePath = covetPath,
                    cardType = mIdentityCardModel.mFirstNellImageType
                )
            )
        } else {
            Toast.makeText(
                this,
                "Please select picture first.",
                Toast.LENGTH_SHORT
            ).show()
        }
    }

    /** 请求相机权限 */
    private fun requestExtPermissoins() {
        requestFirstNellSpecFirstNellPermissions(arrayOf(android.Manifest.permission.CAMERA))
    }

    /** 启动相机预览 */
    private fun startCameraPreview() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            // Used to bind the lifecycle of camers to the lifecycle owner
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

            //Preview
            val preview = Preview.Builder()
                .build()
                .also {
                    it.setSurfaceProvider(mFirstNellActivityFirstNellBinding.previewViewFace.surfaceProvider)
                }

            //设置预览尺寸
            val screenWidth = getFirstNellScreenFirstNellWidth()
            val screenHeight = getFirstNellScreenFirstNellHeight()
            val resolutionStrategy = ResolutionStrategy(
                Size(screenHeight, screenWidth),
                ResolutionStrategy.FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER
            )
            val resolutionSelector = ResolutionSelector.Builder()
                .setResolutionStrategy(resolutionStrategy)
                .build()

            imageCapture = ImageCapture.Builder()
                .setResolutionSelector(resolutionSelector)
                .build()

            //Select back camera as default
            val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA

            try {
                //Unbind use cases before rebinding
                cameraProvider.unbindAll()

                //Bind use cases to camera
                cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture)

            } catch (e: Exception) {
                e.printStackTrace()
            }
        }, ContextCompat.getMainExecutor(this))
    }

    private fun takePhoto() {
        //Get a stable reference of the modifiable image capture use case
        val imageCapture = imageCapture ?: return

        mImageLocalPath = getImageLocalPath()
        val outputOptions = ImageCapture.OutputFileOptions
            .Builder(File(mImageLocalPath!!))
            .build()

        //Set up image captrue listener, which is triggered after photo has been taken
        imageCapture.takePicture(
            outputOptions,
            ContextCompat.getMainExecutor(this),
            object : ImageCapture.OnImageSavedCallback {
                override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
                    try {
                        mImageLocalPath?.let { filePath ->
                            //压缩图片
                            ImageConvert.startConvertImage(File(filePath)) { localPath, thumpImg ->
                                mImageLocalPath = localPath
                                val result = rotateBitmap(thumpImg, localPath)
                                //重置UI
                                updateTakePictureUI(result)
                            }
                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                override fun onError(exception: ImageCaptureException) {
                    println("Photo capture failed: ${exception.message}")
                }
            }
        )
    }

    /** 重置UI */
    private fun updateTakePictureUI(bitmap: Bitmap?) {
        mImageBitmap = bitmap
        if (bitmap == null) {
            mFirstNellActivityFirstNellBinding.imageResult
                .visibility = View.GONE
            mFirstNellActivityFirstNellBinding.imageResult
                .setImageBitmap(null)

            mFirstNellActivityFirstNellBinding.llTakePicture
                .visibility = View.VISIBLE
            mFirstNellActivityFirstNellBinding.llRetake
                .visibility = View.GONE
            mFirstNellActivityFirstNellBinding.llChoose
                .visibility = View.GONE

        } else {
            mFirstNellActivityFirstNellBinding.imageResult
                .visibility = View.VISIBLE
            mFirstNellActivityFirstNellBinding.imageResult
                .setImageBitmap(bitmap)

            mFirstNellActivityFirstNellBinding.llTakePicture
                .visibility = View.GONE
            mFirstNellActivityFirstNellBinding.llRetake
                .visibility = View.VISIBLE
            mFirstNellActivityFirstNellBinding.llChoose
                .visibility = View.VISIBLE
        }
    }

    /** 图片内部路径 */
    private fun getImageLocalPath(): String {
        val imgDir = filesDir.toString() + File.separator + "Pics"
        val dirFile = File(imgDir)
        if (!dirFile.exists()) {
            dirFile.mkdirs()
        }
        val imgName = System.currentTimeMillis().toString() + ".jpg"
        return imgDir + File.separator + imgName
    }

    /**
     * 横向反转图片
     */
    private fun matrixToX(bitmap: Bitmap): Bitmap? {
        val matrix = Matrix()
        matrix.preScale(-1.0f, 1.0f)
        val result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
        bitmap.recycle()
        return result
    }

    /**
     * 根据角度反转图片
     */
    fun rotateBitmap(bitmap: Bitmap, imageFilePath: String?): Bitmap? {
        try {
            val exif = ExifInterface(
                imageFilePath!!
            )
            val orientation = exif.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_UNDEFINED
            )
            val matrix = Matrix()
            when (orientation) {
                ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> matrix.setScale(-1f, 1f)
                ExifInterface.ORIENTATION_ROTATE_180 -> matrix.setRotate(180f)
                ExifInterface.ORIENTATION_FLIP_VERTICAL -> {
                    matrix.setRotate(180f)
                    matrix.postScale(-1f, 1f)
                }
                ExifInterface.ORIENTATION_TRANSPOSE -> {
                    matrix.setRotate(90f)
                    matrix.postScale(-1f, 1f)
                }
                ExifInterface.ORIENTATION_ROTATE_90 -> matrix.setRotate(90f)
                ExifInterface.ORIENTATION_TRANSVERSE -> {
                    matrix.setRotate(-90f)
                    matrix.postScale(-1f, 1f)
                }
                ExifInterface.ORIENTATION_ROTATE_270 -> matrix.setRotate(-90f)
                else -> return bitmap
            }
            return try {
                val rotatedBitmap =
                    Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
                bitmap.recycle()
                rotatedBitmap
            } catch (e: OutOfMemoryError) {
                e.printStackTrace()
                null
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return bitmap
    }
}